const PENDING = 'PENDING';
const FULFILLED = 'FUlFILLED';
const REJECTED = 'REJECTED';
const resolvePromise = (promise2, x, resolve, reject) => {
	if (x === promise2) {
		return reject()
	}
	if ((typeof x === 'object' && x != null) || (typeof x === 'function')) {
		try {
			let called;
			let then = x.then;
	
			if (typeof then === 'function') {
				then.call(x, y => {
					if(called) return;
					called = true;
					resolvePromise(promise2, y, resolve, reject)
				}, r =>{
					if(called) return;
					called = true;
					reject(r);
				})
			} else {
				resolve(x)//为什么不是then
			}
		} catch (e) {
			if(called) return;
			called = true;
			reject(e)
		}
	} else {
		resolve(x)
	}

}

class MyPromise {
	constructor(executor) {
		this.status = PENDING;
		this.value = undefined;
		this.reason = undefined;
		this.onResolveCallbacks = [];
		this.onRejectCallbacks = [];

		let resolve = (value) => {
			if (this.status === PENDING) {
				this.status = FULFILLED;
				this.value = value;
				this.onResolveCallbacks.forEach(fn => fn());
			}
		}
		let reject = (reason) => {
			if (this.status === PENDING) {
				this.status = REJECTED;
				this.reason = reason;
				this.onRejectCallbacks.forEach(fn => fn());
			}
		}
		try {
			executor(resolve, reject);
		} catch (error) {
			error
		}
	}
	then(onFulfilled, onRejected) {
		//判断onFulfilled和onRejected的类型
		onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
		onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err };

		let promise2 = new MyPromise((resolve, reject) => {
			if (this.status === FULFILLED) {
				setTimeout(() => {
					try {
						let x = onFulfilled(this.value);
						resolvePromise(promise2, x, resolve, reject)
					} catch (error) {
						reject(error)
					}
				}
					, 0)
			}
			if (this.status === REJECTED) {
				setTimeout(() => {
					try {
						let x = onRejected(this.reason);
						resolvePromise(promise2, x, resolve, reject);
					} catch (error) {
						reject(error)
					}
				}
					, 0)
			}
			if (this.status === PENDING) {
				this.onResolveCallbacks.push(() => {
					setTimeout(() => {
						try {
							let x = onFulfilled(this.value);
							resolvePromise(promise2, x, resolve, reject)
						} catch (error) {
							reject(error)
						}
					}
						, 0)
				})
				this.onRejectCallbacks.push(() => {
					setTimeout(() => {
						try {
							let x = onRejected(this.reason);
							resolvePromise(promise2, x, resolve, reject);
						} catch (error) {
							reject(error)
						}
					}
						, 0)
				})
			}
		})
		return promise2;
	}
}


